// poj1151
// 题意：
// n(<=100)个矩形（坐标可能浮点，坐标范围[0, 10^5]），求面积并。
//
// 题解：
// 线段树 + 扫描线模板题。
// 首先要离散化，如果你是从左往右扫描竖直线段就离散化y坐标，
// 离散化后第i个位置点表示i到i+1这段线段，线段树维护两个标记，
// 一个是这段区间被覆盖长度和，一个是这段区间被完全覆盖的次数。
// 然后从左往右扫描一条条竖直线段，相邻两个位置算下对面积总和的贡献，
// 不断update线段树就行。
//
// ml:run = $bin < input
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>

struct seg { double l, r, pos; int cover; };
bool operator<(seg const& a, seg const& b)
{
    return a.pos < b.pos || (a.pos == b.pos && a.cover > b.cover);
}

int const maxn = 1000;
// segment tree, tree for length sum, cover for covered times
double tree[4 * maxn];
int cover[4 * maxn];

// all discreate segment
seg segs[maxn * 2];
int tot;

// discreate y pos
double dis[maxn * 2];
int len;

int n;

void init()
{
    tot = len = 0;
    std::memset(tree, 0, sizeof(tree));
    std::memset(cover, 0, sizeof(cover));
}

void push_up(int id, int l, int r)
{
    if (cover[id]) tree[id] = dis[r + 1] - dis[l];
    else if (l == r) tree[id] = 0;
    else tree[id] = tree[id * 2] + tree[id * 2 + 1];
}

void update(int id, int l, int r, int tl, int tr, int d)
{
    if (tl <= l && r <= tr) { cover[id] += d; push_up(id, l, r); return; }
    int mid = (l + r) / 2;
    if (tl <= mid) update(id * 2, l, mid, tl, tr, d);
    if (tr > mid) update(id * 2 + 1, mid + 1, r, tl, tr, d);
    push_up(id, l, r);
}

int main()
{
    std::ios_base::sync_with_stdio(false);
    for (int ti = 1; std::cin >> n && n; ti++) {
        std::cout << "Test case #" << ti << "\nTotal explored area: ";
        init();
        for (int i = 0; i < n; i++) {
            double x1, y1, x2, y2; std::cin >> x1 >> y1 >> x2 >> y2;
            segs[tot].pos = x1;
            segs[tot].l = y1;
            segs[tot].r = y2;
            segs[tot++].cover = 1;

            segs[tot].pos = x2;
            segs[tot].l = y1;
            segs[tot].r = y2;
            segs[tot++].cover = -1;

            dis[len++] = y1; dis[len++] = y2;
        }
        std::sort(dis, dis + len);
        len = std::unique(dis, dis + len) - dis;

        std::sort(segs, segs + tot);
        double ans = 0;
        for (int i = 0; i < tot; i++) {
            int l = std::lower_bound(dis, dis + len, segs[i].l) - dis;
            int r = std::lower_bound(dis, dis + len, segs[i].r) - dis - 1;
            if (l > r) continue;
            if (i) ans += (segs[i].pos - segs[i - 1].pos) * tree[1];
            /* if (i) std::cerr << ans << " " << segs[i].pos - segs[i - 1].pos << " " << std::fixed << std::setprecision(2) << tree[1] << "\n"; */
            /* std::cerr << "::  " << l << " " << r << " " << len << "\n"; */
            update(1, 0, len - 1, l, r, segs[i].cover);
        }

        std::cout << std::fixed << std::setprecision(2) << ans << "\n\n";
    }
}

